﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Cms.Application.Admin.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;
using Cms.Utilities;
using iLib.Web.UI;

namespace Cms.Application.Admin.Presenters
{
    public class EditApplicationPagePresenter : EditPagePresenter
    {
        private readonly IEditApplicationPageView _view;

        public EditApplicationPagePresenter(IEditApplicationPageView view)
            : this(view, new RepositoryFactory())
        {
            DiskAccess = new DiskAccess();
        }
        
        public EditApplicationPagePresenter(IEditApplicationPageView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            Administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!Administrator.HasPermission.EditApplicationPage)
                _view.RedirectToPermissionDeniedPage();
        }

        public override void Initialize()
        {
            base.Initialize();
            SetAreas();
            if (_view.PageID == -1)
            {
                _view.Code = DiskAccess.ReadTextFile("Admin\\Resources\\ApplicationPageTemplate.aspx");
            }
            else
            {
                var page = (ApplicationPage)PageRepository.GetPage(_view.PageID);
                _view.ApplicationID = page.Application.ID;
                _view.Code = page.GetCode();
            }
            SaveSourceCodePreview();
        }

        public void SetAreas()
        {
            MasterTemplate mt = SiteRepository.GetMasterTemplate(_view.SelectedMasterTemplateID);
            DetailTemplate dt = SiteRepository.GetDetailTemplate(_view.SelectedDetailTemplateID);
            IList<string> areas = mt.PageAreas.ToList();
            foreach (string area in dt.PageAreas)
            {
                areas.Add(area);
            }
            _view.SetAreas(areas);
            _view.SelectedArea = areas[0];
            UpdateAreaSourceCode();
        }
        
        public override void Validate()
        {
            base.Validate();
            if (_view.CurrentTab != "design" && _view.CurrentTab != "code")
            {
                return;
            }
            SaveSourceCodePreview();
            string sourceCodeValidationResult = _view.GetSourceCodeStatus();
            if (sourceCodeValidationResult == "ok")
            {
                return;
            }
            string errorText = GetText(_view, "SourceCodeError");
            errorText = errorText.Replace("[[ErrorMessage]]", sourceCodeValidationResult);
            string encryptedCredentials = Cipher.Encrypt(Administrator.Username + (char)9 + Administrator.Password);
            string url = Url.FullPath + "Admin/Default.aspx?credentials=" +
                         HttpUtility.UrlEncode(encryptedCredentials) + "&ReturnUrl=" +
                         HttpUtility.UrlEncode(_view.UserTempDirectory + "ErrorDetails.aspx?v=" + DateTime.Now.Ticks);
            errorText = errorText.Replace("[[ErrorDetailsUrl]]", url);
            AddValidationError(errorText);
        }
        
        public override void Save()
        {
            Validate();
            if (!IsValid)
            {
                return;
            }
            ApplicationPage page;
            if (_view.PageID == -1)
            {
                page = new ApplicationPage
                           {
                               Site = Administrator.CurrentSite,
                               Application = SiteRepository.GetApplication(_view.ApplicationID)
                           };
            }
            else
            {
                page = (ApplicationPage)PageRepository.GetPage(_view.PageID);
            }
            string originalVirtualPath = page.GetVirtualPath();
            GetBasicPropertiesViewData(page);
            GetLocalizedPropertiesViewData(page);

            // Save basic properties to get an ID from the database
            PageRepository.SaveApplicationPage(page);

            // Create the file using the ID as filename
            SaveSourceCode(page);

            //TODO: Check Areas!!!

            // Save again to persist the code
            PageRepository.SaveApplicationPage(page);
            if (_view.PageID > 0 && page.GetVirtualPath() != originalVirtualPath)
            {
                var frm = new FileReferencesManager(Administrator, SiteRepository, ContentRepository, DiskAccess);
                frm.UpdateFileReferences(originalVirtualPath, page.GetVirtualPath(), Administrator.CurrentSite.ID);
            }
            _view.SetPageID(page.ID);
        }
        
        public void SaveSourceCodePreview()
        {
            var ap = (ApplicationPage)PageRepository.GetPage(_view.PageID);
            if (ap == null)
            {
                return;
            }
            string code = _view.Code.Replace("Inherits=\"Cms.Web.Framework.Controls.Page\"", "Inherits=\"Cms.Web.Framework.Controls.SitePreview\"");
            if (!code.EndsWith(Environment.NewLine))
            {
                code += Environment.NewLine;
            }
            foreach (var kvp in ap.Areas)
            {
                code += "<asp:Content ID=\"" + kvp.Key + "\" ContentPlaceHolderID=\"" + kvp.Key + "\" runat=\"server\">";
                if (kvp.Key == _view.CurrentArea)
                {
                    code += _view.Design;
                }
                else
                {
                    code += kvp.Value.CurrentVersion.Code;
                }
                code += "</asp:Content>" + Environment.NewLine;
            }
            if (ap.Areas.Count == 0)
            {
                code += "<asp:Content ID=\"" + _view.CurrentArea + "\" ContentPlaceHolderID=\"" + _view.CurrentArea + "\" runat=\"server\">";
                code += _view.Design;
                code += "</asp:Content>" + Environment.NewLine;
            }
            DiskAccess.DeleteFile(_view.UserPhysicalTempDirectory + "\\ApplicationPagePreview.aspx");
            DiskAccess.CreateTextFile(_view.UserPhysicalTempDirectory + "\\ApplicationPagePreview.aspx", code);
        }

        public void UpdateAreaSourceCode()
        {
            var ap = (ApplicationPage)PageRepository.GetPage(_view.PageID);
            _view.Design = ap != null ? ap.GetAreaDesign(_view.SelectedArea) : string.Empty;
        }
        
        private void SaveSourceCode(ApplicationPage page)
        {
            page.SetAreaDesign(_view.CurrentArea, _view.Design, Administrator);
            page.SetCode(_view.Code, Administrator);
            string code = _view.Code;
            if (!code.EndsWith(Environment.NewLine))
            {
                code += Environment.NewLine;
            }
            foreach (var kvp in page.Areas)
            {
                code += "<asp:Content ID=\"" + kvp.Key + "\" ContentPlaceHolderID=\"" + kvp.Key + "\" runat=\"server\">";
                code += kvp.Value.CurrentVersion.Code;
                code += "</asp:Content>" + Environment.NewLine;
            }
            DiskAccess.CreateDirectory("__System\\ApplicationPages");
            DiskAccess.DeleteFile("__System\\ApplicationPages\\" + page.ID + ".aspx");
            DiskAccess.CreateTextFile("__System\\ApplicationPages\\" + page.ID + ".aspx", code);
        }
    }
}